<?php
/**
 * 工作流审批服务
 * 统一管理各种业务类型的审批流程
 */

declare(strict_types=1);

namespace app\service;

use think\facade\Db;
use think\facade\Log;

class WorkflowService
{
    /**
     * 支持的审批类型
     */
    public const APPROVAL_TYPES = [
        'official_docs' => '公文审批',
        'seal' => '用章审批', 
        'contract' => '销售合同审批',
        'purchase' => '采购合同审批',
        'expense' => '报销审批',
        'invoice' => '发票审批',
        'ticket' => '收票审批'
    ];

    /**
     * 审批状态
     */
    public const STATUS = [
        'PENDING' => 0,      // 待审批
        'PROCESSING' => 1,   // 审批中
        'APPROVED' => 2,     // 已通过
        'REJECTED' => 3,     // 已拒绝
        'CANCELLED' => 4     // 已取消
    ];

    /**
     * 创建审批流程
     * @param string $type 审批类型
     * @param int $businessId 业务记录ID
     * @param int $applicantId 申请人ID
     * @param array $approvers 审批人ID数组
     * @param string $title 审批标题
     * @param array $content 审批内容
     * @return int 审批流程ID
     * @throws \Exception
     */
    public function createApproval(string $type, int $businessId, int $applicantId, array $approvers, string $title, array $content = []): int
    {
        if (!isset(self::APPROVAL_TYPES[$type])) {
            throw new \Exception('不支持的审批类型: ' . $type);
        }

        if (empty($approvers)) {
            throw new \Exception('审批人不能为空');
        }

        if (empty($title)) {
            throw new \Exception('审批标题不能为空');
        }

        Db::startTrans();
        try {
            // 创建主审批记录
            $approvalData = [
                'type' => $type,
                'business_id' => $businessId,
                'title' => $title,
                'content' => json_encode($content, JSON_UNESCAPED_UNICODE),
                'applicant_id' => $applicantId,
                'approver_ids' => implode(',', $approvers),
                'current_step' => 1,
                'total_steps' => count($approvers),
                'status' => self::STATUS['PENDING'],
                'create_time' => time(),
                'update_time' => time()
            ];

            $approvalId = Db::name('workflow_approval')->insertGetId($approvalData);

            // 创建审批步骤记录
            $stepData = [];
            foreach ($approvers as $index => $approverId) {
                $stepData[] = [
                    'approval_id' => $approvalId,
                    'step_number' => $index + 1,
                    'approver_id' => $approverId,
                    'status' => $index === 0 ? self::STATUS['PENDING'] : self::STATUS['PENDING'],
                    'create_time' => time()
                ];
            }
            
            Db::name('workflow_approval_step')->insertAll($stepData);

            // 更新业务表的审批状态
            $this->updateBusinessApprovalStatus($type, $businessId, self::STATUS['PENDING'], implode(',', $approvers));

            Db::commit();

            // 发送审批通知（如果有通知系统）
            $this->sendApprovalNotification($approvalId, $approvers[0]);

            return $approvalId;
        } catch (\Exception $e) {
            Db::rollback();
            Log::error('创建审批流程失败: ' . $e->getMessage(), [
                'type' => $type,
                'business_id' => $businessId,
                'applicant_id' => $applicantId
            ]);
            throw $e;
        }
    }

    /**
     * 处理审批
     * @param int $approvalId 审批ID
     * @param int $approverId 审批人ID
     * @param int $action 审批动作 (2=通过, 3=拒绝)
     * @param string $remark 审批意见
     * @return bool
     * @throws \Exception
     */
    public function processApproval(int $approvalId, int $approverId, int $action, string $remark = ''): bool
    {
        if (!in_array($action, [self::STATUS['APPROVED'], self::STATUS['REJECTED']])) {
            throw new \Exception('无效的审批动作');
        }

        Db::startTrans();
        try {
            // 获取审批信息
            $approval = Db::name('workflow_approval')->where('id', $approvalId)->find();
            if (!$approval) {
                throw new \Exception('审批记录不存在');
            }

            if ($approval['status'] != self::STATUS['PENDING'] && $approval['status'] != self::STATUS['PROCESSING']) {
                throw new \Exception('审批已完成，无法操作');
            }

            // 获取当前审批步骤
            $currentStep = Db::name('workflow_approval_step')
                ->where('approval_id', $approvalId)
                ->where('step_number', $approval['current_step'])
                ->find();

            if (!$currentStep || $currentStep['approver_id'] != $approverId) {
                throw new \Exception('当前不是您的审批环节');
            }

            // 更新当前步骤
            Db::name('workflow_approval_step')
                ->where('id', $currentStep['id'])
                ->update([
                    'status' => $action,
                    'remark' => $remark,
                    'approve_time' => time(),
                    'update_time' => time()
                ]);

            // 记录审批历史
            $this->recordApprovalHistory($approvalId, $approverId, $action, $remark);

            // 判断审批结果
            if ($action == self::STATUS['REJECTED']) {
                // 拒绝 - 整个流程结束
                $this->completeApproval($approvalId, self::STATUS['REJECTED']);
            } else {
                // 通过 - 检查是否还有下一步
                if ($approval['current_step'] >= $approval['total_steps']) {
                    // 所有步骤完成 - 审批通过
                    $this->completeApproval($approvalId, self::STATUS['APPROVED']);
                } else {
                    // 进入下一步审批
                    $nextStep = $approval['current_step'] + 1;
                    Db::name('workflow_approval')
                        ->where('id', $approvalId)
                        ->update([
                            'current_step' => $nextStep,
                            'status' => self::STATUS['PROCESSING'],
                            'update_time' => time()
                        ]);

                    // 通知下一个审批人
                    $nextApprover = Db::name('workflow_approval_step')
                        ->where('approval_id', $approvalId)
                        ->where('step_number', $nextStep)
                        ->value('approver_id');

                    if ($nextApprover) {
                        $this->sendApprovalNotification($approvalId, $nextApprover);
                    }
                }
            }

            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            Log::error('处理审批失败: ' . $e->getMessage(), [
                'approval_id' => $approvalId,
                'approver_id' => $approverId,
                'action' => $action
            ]);
            throw $e;
        }
    }

    /**
     * 获取用户的待审批列表
     * @param int $userId 用户ID
     * @param array $params 查询参数
     * @return array
     */
    public function getPendingApprovals(int $userId, array $params = []): array
    {
        $page = (int)($params['page'] ?? 1);
        $limit = (int)($params['limit'] ?? 10);

        $where = [];
        $where[] = ['s.approver_id', '=', $userId];
        $where[] = ['s.status', '=', self::STATUS['PENDING']];
        $where[] = ['a.status', 'in', [self::STATUS['PENDING'], self::STATUS['PROCESSING']]];

        // 类型筛选
        if (!empty($params['type'])) {
            $where[] = ['a.type', '=', $params['type']];
        }

        $list = Db::name('workflow_approval_step')
            ->alias('s')
            ->join('workflow_approval a', 's.approval_id = a.id')
            ->join('admin u', 'a.applicant_id = u.id', 'LEFT')
            ->field('a.id, a.type, a.title, a.business_id, a.create_time, u.name as applicant_name, s.step_number, a.total_steps')
            ->where($where)
            ->page($page, $limit)
            ->order('a.create_time', 'desc')
            ->select()
            ->each(function($item) {
                $item['type_name'] = self::APPROVAL_TYPES[$item['type']] ?? $item['type'];
                $item['create_time'] = date('Y-m-d H:i:s', $item['create_time']);
                return $item;
            })
            ->toArray();

        $total = Db::name('workflow_approval_step')
            ->alias('s')
            ->join('workflow_approval a', 's.approval_id = a.id')
            ->where($where)
            ->count();

        return [
            'list' => $list,
            'total' => $total,
            'page' => $page,
            'limit' => $limit
        ];
    }

    /**
     * 获取审批详情
     * @param int $approvalId 审批ID
     * @return array
     */
    public function getApprovalDetail(int $approvalId): array
    {
        $approval = Db::name('workflow_approval')
            ->alias('a')
            ->join('admin u', 'a.applicant_id = u.id', 'LEFT')
            ->field('a.*, u.name as applicant_name')
            ->where('a.id', $approvalId)
            ->find();

        if (!$approval) {
            throw new \Exception('审批记录不存在');
        }

        // 获取审批步骤
        $steps = Db::name('workflow_approval_step')
            ->alias('s')
            ->join('admin u', 's.approver_id = u.id', 'LEFT')
            ->field('s.*, u.name as approver_name')
            ->where('s.approval_id', $approvalId)
            ->order('s.step_number', 'asc')
            ->select()
            ->toArray();

        // 获取审批历史
        $history = Db::name('workflow_approval_history')
            ->alias('h')
            ->join('admin u', 'h.approver_id = u.id', 'LEFT')
            ->field('h.*, u.name as approver_name')
            ->where('h.approval_id', $approvalId)
            ->order('h.create_time', 'desc')
            ->select()
            ->toArray();

        $approval['content'] = $approval['content'] ? json_decode($approval['content'], true) : [];
        $approval['type_name'] = self::APPROVAL_TYPES[$approval['type']] ?? $approval['type'];
        $approval['status_name'] = $this->getStatusName($approval['status']);
        $approval['steps'] = $steps;
        $approval['history'] = $history;

        return $approval;
    }

    /**
     * 完成审批流程
     * @param int $approvalId 审批ID
     * @param int $finalStatus 最终状态
     * @throws \Exception
     */
    private function completeApproval(int $approvalId, int $finalStatus): void
    {
        $approval = Db::name('workflow_approval')->where('id', $approvalId)->find();
        if (!$approval) {
            throw new \Exception('审批记录不存在');
        }

        // 更新审批状态
        Db::name('workflow_approval')
            ->where('id', $approvalId)
            ->update([
                'status' => $finalStatus,
                'complete_time' => time(),
                'update_time' => time()
            ]);

        // 更新业务表状态
        $this->updateBusinessApprovalStatus($approval['type'], $approval['business_id'], $finalStatus);

        // 发送完成通知
        $this->sendCompletionNotification($approvalId, $finalStatus);
    }

    /**
     * 更新业务表的审批状态
     * @param string $type 业务类型
     * @param int $businessId 业务ID
     * @param int $status 审批状态
     * @param string $approverIds 审批人ID列表
     */
    protected function updateBusinessApprovalStatus(string $type, int $businessId, int $status, string $approverIds = ''): void
    {
        $updateData = ['check_status' => $status];
        if ($approverIds) {
            $updateData['check_uids'] = $approverIds;
        }

        switch ($type) {
            case 'official_docs':
                Db::name('official_docs')->where('id', $businessId)->update($updateData);
                break;
            case 'seal':
                Db::name('seal')->where('id', $businessId)->update($updateData);
                break;
            case 'contract':
                Db::name('contract')->where('id', $businessId)->update($updateData);
                break;
            case 'purchase':
                Db::name('purchase')->where('id', $businessId)->update($updateData);
                break;
            case 'expense':
                Db::name('expense')->where('id', $businessId)->update($updateData);
                break;
            case 'invoice':
                Db::name('invoice')->where('id', $businessId)->update($updateData);
                break;
            case 'ticket':
                Db::name('ticket')->where('id', $businessId)->update($updateData);
                break;
            case 'project_task':
                Db::name('project_task')->where('id', $businessId)->update($updateData);
                break;
        }
    }

    /**
     * 记录审批历史
     * @param int $approvalId 审批ID
     * @param int $approverId 审批人ID
     * @param int $action 审批动作
     * @param string $remark 审批意见
     */
    private function recordApprovalHistory(int $approvalId, int $approverId, int $action, string $remark): void
    {
        Db::name('workflow_approval_history')->insert([
            'approval_id' => $approvalId,
            'approver_id' => $approverId,
            'action' => $action,
            'remark' => $remark,
            'create_time' => time()
        ]);
    }

    /**
     * 发送审批通知
     * @param int $approvalId 审批ID
     * @param int $approverId 审批人ID
     */
    private function sendApprovalNotification(int $approvalId, int $approverId): void
    {
        // TODO: 实现消息通知功能
        // 可以发送站内消息、邮件通知等
        Log::info('审批通知发送', [
            'approval_id' => $approvalId,
            'approver_id' => $approverId
        ]);
    }

    /**
     * 发送完成通知
     * @param int $approvalId 审批ID
     * @param int $finalStatus 最终状态
     */
    private function sendCompletionNotification(int $approvalId, int $finalStatus): void
    {
        // TODO: 实现完成通知功能
        Log::info('审批完成通知', [
            'approval_id' => $approvalId,
            'final_status' => $finalStatus
        ]);
    }

    /**
     * 获取状态名称
     * @param int $status 状态码
     * @return string
     */
    private function getStatusName(int $status): string
    {
        $statusNames = [
            self::STATUS['PENDING'] => '待审批',
            self::STATUS['PROCESSING'] => '审批中',
            self::STATUS['APPROVED'] => '已通过',
            self::STATUS['REJECTED'] => '已拒绝',
            self::STATUS['CANCELLED'] => '已取消'
        ];

        return $statusNames[$status] ?? '未知状态';
    }
}